{# What one meeting came to, drawn the same on the Meetings page and in Overseer's drawer. ``clock`` maps a transcript line's id to its time. #} {% from "components/macros/feedback.html" import empty_state %} {% import "components/macros/layout.html" as layout %} {% from "components/macros/layout.html" import badge, chart_dot %} {# Where the bot is with the call, and how long it was in. #} {% macro status_line(status, length) %} {{ badge(status.label, status.tone) }} {% if length %}{{ length }}{% endif %} {% endmacro %} {% macro failure(meeting) %} {% if meeting.failure_reason %}{% endif %} {% endmacro %} {# What the bot did on Meet's page (``models.bot``), a value for the meeting's ``facts`` (pass it only with steps): each control in turn, plain where it went as it should, marked in its tone where not (Meet's shortcut, or not found), then why it left. A step with what the page showed opens on it: the buttons Meet had, for what a renamed control is called now. #} {% macro bot_steps(steps) -%} {% for s in steps %} {% if not loop.first %}{% endif %} {% set said = s.said if s.tone == "ok" else badge(s.said, s.tone) %} {% if s.seen %}
{{ said }}

{{ s.seen }}

{% else %}{{ said }}{% endif %} {% endfor %}
{%- endmacro %} {# The notes, or why there are none: the summary, then what the caller puts first (the Meetings page puts my items there), then the lists. A rewrite that failed keeps the notes it had, and says so above them. #} {% macro notes_view(notes, notes_error, clock, empty, voices) %} {% if notes %} {% if notes_error %}{% endif %}

{{ notes.summary }}

{% if caller is defined %}{{ caller() }}{% endif %} {{ notes_lists(notes, clock, voices) }} {% elif notes_error %} {% else %}

{{ empty }}

{% endif %} {% endmacro %} {# A speaker as the theme marks a source (the logs page's dot): their name in text, after a small dot in their color in this meeting (``voices``). #} {% macro speaker(name, voices, attr="data-speaker") -%} {{ chart_dot(voices.get(name, 1)) }}{{ name }} {%- endmacro %} {% macro items(list, empty, clock, voices=None) %} {% if list %} {% else %}

{{ empty }}

{% endif %} {% endmacro %} {% macro heading(label) %}

{{ label }}

{% endmacro %} {# Everyone's action items, the decisions and the open questions. #} {% macro notes_lists(notes, clock, voices) %}
{{ heading("Everyone's") }} {{ items(notes.action_items, "No action items.", clock, voices) }}
{{ heading("Decisions") }} {{ items(notes.decisions, "No decisions.", clock) }}
{{ heading("Open questions") }} {{ items(notes.open_questions, "None left open.", clock) }}
{% endmacro %} {# Who said what: one speaker's lines in a row under their name, each line with its time and its own anchor (an item jumps to it); ``hit``, the line a search opened it at, marked. #} {# ``base`` and ``asks``: each line can be asked what it is about (where the stack has Illiana), her answer opening under it in a slot the body's live re-read keeps (``hx-preserve``). The slot holds the ask too: one at a time (``hx-sync``), and saying she is on it (``hx-indicator``), however often the body is drawn again meanwhile. ``parts``: the parts of the system a line names (``parts_named``), each offered as what it is. #} {% macro transcript(turns, clock, voices, hit=None, base=None, asks=False, parts={}) %} {% if turns %}
    {% for name, rows in turns %}
  1. {{ speaker(name, voices) }} {% for line in rows %}

    {{ clock[line.id] }} {{ line.text }}{% for part, name in parts.get(line.id, []) %} {{ ask_about(base, line.id, part, name) }}{% endfor %} {% if asks %}{{ ask_about(base, line.id) }}{% endif %}

    {% if asks %}
    {% endif %} {% endfor %}
  2. {% endfor %}
{% else %} {{ empty_state("Nothing said yet", "Lines appear here as the call's captions write them.") }} {% endif %} {% endmacro %} {# One moment as its card shows it: who, when, and what was said. #} {% macro said_line(moment, clock, voices) -%}
{{ speaker(moment.speaker, voices) }} {{ clock.get(moment.line_id, "") }}

{{ moment.text }}

{%- endmacro %} {# What the call threw up of one kind (``moments``): each with who said it and when, a button per action it offers (a browser action copies its prompt; the others are asked, at ``base``), and every run asked of it, with where it stands and what it came back with. #} {% macro moments(list, clock, voices, base, hx_body) %} {% from "components/macros/form.html" import action %} {% from "components/macros/layout.html" import copy_button, fold_mark %} {# A run's tone (``RunRecord.tone``) as its dot and its answer's edge. #} {% set dots = {"ok": "bg-aegis-teal", "error": "bg-aegis-error", "muted": "bg-aegis-border"} %} {% set edges = {"ok": "border-aegis-teal", "error": "border-aegis-error", "muted": "border-aegis-border"} %} {% endmacro %} {# Asking Illiana what a line is about (``.ask-about``): shown on the line's hover (or focus), her answer drawn into the slot after it (``transcript``). Kept small: a live call draws every line again every few seconds. Given a ``part`` the line names (heard as ``name``), a chip asking what it is. #} {% macro ask_about(base, line_id, part=None, name=None) -%} {%- set url = base ~ "/lines/" ~ line_id ~ "/about" -%} {%- if part -%} {%- set hx %}hx-post="{{ url }}?part={{ part|urlencode }}"{% endset -%} {%- set extra %}data-part="{{ part }}"{% endset -%} {{ layout.chip(name ~ ": what it is", hx=hx, extra=extra) }} {%- else -%} {%- endif -%} {%- endmacro %}